use crate::config::{create_data_item_service, create_settings_service};
use crate::global_var::{GLOBAL_QUEUE, GLOBAL_TASK_MANAGER};
use crate::models::DataItem;
use crate::utils::{
    get_urls, Client, ImageMessageItem, Message, MessageItem, TaskManager, TaskStatus,
};
use pyo3::prelude::*;
use pyo3::types::PyTuple;
use reqwest::header::{HeaderMap, ACCEPT};
use serde_json::json;
use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::Semaphore;
use tokio::task;
use uuid::Uuid;

#[tauri::command]
pub async fn run_playwright(base_url: String) {
    let task_manager = GLOBAL_TASK_MANAGER.clone();
    let url_list = get_urls(&base_url).await;
    let settings_service = create_settings_service();
    let server_address = match settings_service.get_setting("server_address") {
        Ok(Some(value)) => value,
        Ok(None) => {
            println!("Setting not found");
            return;
        }
        Err(e) => {
            println!("Error occurred: {}", e);
            return;
        }
    };
    let max_concurrency = settings_service
        .get_setting("concurrency")
        .unwrap()
        .unwrap_or("10".to_string());
    let semaphore = Arc::new(Semaphore::new(max_concurrency.parse().unwrap_or(10)));
    let mut proxy = settings_service.get_setting("proxy").unwrap();
    if proxy.is_none() {
        proxy = Some("".to_string());
    }
    if url_list.len() == 0 {
        let client = Client::new(GLOBAL_QUEUE.clone());
        let stop_task = HashMap::from([
            ("data".to_string(), "finished".to_string()),
            ("status".to_string(), "stop".to_string()),
        ]);
        client.send(Message::Data(MessageItem {
            name: "data-task-message".to_string(),
            value: stop_task.clone(),
        }));
        println!("All tasks completed. Sent completion event.");
    }
    for url in url_list {
        let task_id: String = Uuid::new_v4().to_string(); // 生成唯一任务 ID
        task_manager.register_task(task_id.clone());
        let server_address_clone = server_address.clone();
        let task_manager = task_manager.clone(); // 现在可以调用 clone() 方法
        let semaphore = semaphore.clone();
        let base_url = base_url.clone();
        let proxy = proxy.clone();
        tokio::spawn(async move {
            // 获取信号量许可，控制并发
            let permit = match semaphore.acquire().await {
                Ok(p) => p,
                Err(e) => {
                    eprintln!("Failed to acquire semaphore: {:?}", e);
                    return;
                }
            };

            // 执行任务逻辑
            if let Err(e) = process_url(
                url,
                task_id.clone(),
                base_url,
                proxy,
                task_manager,
                server_address_clone,
            )
            .await
            {
                eprintln!("Task failed: {:?}", e);
            }

            // 释放信号量许可
            drop(permit);
        });
    }
}

async fn process_url(
    url: String,
    task_id: String,
    base_url: String,
    proxy: Option<String>,
    task_manager: Arc<TaskManager>,
    server_address: String,
) -> Result<(), Box<dyn std::error::Error>> {
    let data_item_service = create_data_item_service();
    let client = Client::new(GLOBAL_QUEUE.clone());

    // 更新任务状态为 Running
    task_manager.update_task_status(task_id.clone(), TaskStatus::Running);

    let base_url_clone = base_url.clone();

    // 将阻塞操作放到 spawn_blocking 中
    let result = match task::spawn_blocking(move || {
        pyo3::prepare_freethreaded_python();
        Python::with_gil(|py| -> Result<HashMap<String, String>, PyErr> {
            let lib = py.import("lib")?;
            let args = PyTuple::new(
                py,
                &[
                    url.to_string(),
                    base_url_clone.to_string(),
                    proxy.unwrap_or("".to_string()),
                ],
            )?;
            let result: HashMap<String, String> =
                match lib.call_method("run", args, None)?.extract() {
                    Ok(value) => value,
                    Err(_err) => {
                        let mut result_faild = HashMap::<String, String>::new();
                        result_faild.insert("w_status".to_string(), "error".to_string());
                        result_faild.insert("q_pageUrl".to_string(), url);
                        result_faild.insert("error".to_string(), "".to_string());
                        result_faild
                    }
                };
            Ok(result)
        })
    })
    .await? {
        Ok(value) => value,
        Err(e) => {
            println!("{:?}", e.to_string());
            let mut result_faild = HashMap::<String, String>::new();
            result_faild.insert("w_status".to_string(), "error".to_string());
            result_faild.insert("error".to_string(), e.to_string());
            result_faild
        }
    };

    // 处理结果
    client.send(Message::Data(MessageItem {
        name: "data-task-message".to_string(),
        value: result.clone(),
    }));

    let data_item = DataItem {
        id: None,
        name: base_url.to_string(),
        value: json!(result),
        created_at: None,
        updated_at: None,
    };

    // 将数据库操作放到 spawn_blocking 中
    task::spawn_blocking(move || data_item_service.insert_data_item(&data_item))
        .await?
        .map_err(|e| Box::new(e) as Box<dyn std::error::Error>)?;

    // println!("Client: Sent Data message: {:?}", result);

    let pageurl = match result.get("q_pageUrl") {
        Some(value) => value.to_string(),
        None => {
            return Err("q_pageUrl not found in result".into());
        }
    };

    // 判断result的status是否为success
    async fn update_status(status: &str, pageurl: &str, server_address: &str) {
        let client = reqwest::Client::new();
        let mut headers = HeaderMap::new();
        headers.insert(
            ACCEPT,
            reqwest::header::HeaderValue::from_static("application/json"),
        );
        let full_url = format!(
            "{}/api/goods/update_status?url={}&status={}",
            server_address, pageurl, status
        );
        let _ = client.get(&full_url).headers(headers).send().await;
    }

    if result.get("w_status") == Some(&"success".to_string()) {
        task_manager.update_task_status(task_id.clone(), TaskStatus::Success);
        let urls = match result.get("d_imageUrl") {
            Some(value) => {
                let urls: Vec<_> = value.split('|').map(String::from).collect();
                urls
            }
            None => {
                return Err("d_imageUrl not found in result".into());
            }
        };
        let paths = match result.get("c_image") {
            Some(value) => {
                let paths: Vec<_> = value.split('|').map(String::from).collect();
                paths
            }
            None => {
                return Err("c_image not found in result".into());
            }
        };
        for i in 0..urls.len() {
            client.send(Message::DownLoad(ImageMessageItem {
                url: urls[i].clone(),
                path: paths[i].clone()
            }));
        };
        update_status("2", &pageurl, &server_address).await;
    } else {
        task_manager.update_task_status(task_id.clone(), TaskStatus::Failed);
        update_status("3", &pageurl, &server_address).await;
    }

    // 更新任务状态为 Success

    // 获取任务进度并发送给前端
    let (total_tasks, failed_tasks, completed_tasks) = task_manager.get_progress();
    let progress_message = HashMap::from([
        ("total_tasks".to_string(), total_tasks.to_string()),
        ("failed_tasks".to_string(), failed_tasks.to_string()),
        ("completed_tasks".to_string(), completed_tasks.to_string()),
    ]);
    client.send(Message::Data(MessageItem {
        name: "data-task-message-progress".to_string(),
        value: progress_message.clone(),
    }));

    // 检查所有任务是否完成
    if task_manager.all_tasks_completed() {
        let stop_task = HashMap::from([
            ("data".to_string(), "finished".to_string()),
            ("status".to_string(), "stop".to_string()),
        ]);
        client.send(Message::Data(MessageItem {
            name: "data-task-message".to_string(),
            value: stop_task.clone(),
        }));
        println!("All tasks completed. Sent completion event.");
    }

    Ok(())
}
